package org.apache.dolphinscheduler.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.*;
import org.apache.dolphinscheduler.api.utils.DateUtil;
import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.utils.DateUtils;
import org.apache.dolphinscheduler.dao.entity.*;
import org.apache.dolphinscheduler.dao.mapper.UserPayDetailMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Objects;

@Service
public class UserPayDetailServiceImpl extends ServiceImpl<UserPayDetailMapper, UserPayDetail> implements UserPayDetailService {

	@Autowired
	private UsersService usersService;
	@Autowired
	private RechargeApplyService rechargeApplyService;
	@Autowired
	private ProductOrderService productOrderService;
	@Autowired
	private BillService billService;
	@Autowired
	private CouponbillService couponbillService;
	@Autowired
	private CouponService couponDetailService;

	public Result<Object> rechage(User loginUser, Integer rechargeApplyId) {
		Result<Object> result = new Result<>();

		if (loginUser.getRoleId() != null && loginUser.getRoleId().intValue() != 1) {
            result.setCode(Status.USER_NO_OPERATION_PERM.getCode());
        	result.setMsg(Status.USER_NO_OPERATION_PERM.getMsg());
            return result;
        }
		RechargeApply ra = rechargeApplyService.getById(rechargeApplyId);
		if(ra == null) {
			result.setCode(Status.ERROR.getCode());
        	result.setMsg(Status.ERROR.getMsg());
            return result;
		}
		User user = usersService.queryUser(ra.getUserId());
		if(user == null) {
			result.setCode(Status.USER_NOT_EXIST.getCode());
        	result.setMsg(MessageFormat.format(Status.USER_NOT_EXIST.getMsg(), ""));
            return result;
		}
		BigDecimal userBalance = user.getBalance() != null ? user.getBalance() : new BigDecimal(0);
		user.setBalance(userBalance.add(ra.getTransferPrice()));
		usersService.updateById(user);
		// 记录充值明细
		savePayDetail(user.getId(), ra.getTransferPrice(), userBalance, user.getUserName(),userBalance.add(ra.getTransferPrice()));
		ra.setPayStatus(1);
		rechargeApplyService.updateById(ra);
		result.setCode(Status.SUCCESS.getCode());
    	result.setMsg(Status.SUCCESS.getMsg());
        return result;
	}

	public Result<Object> orderPay(User loginUser, Integer orderId, Integer couponDetailId) {
		Result<Object> result = new Result<>();
		ProductOrder po = productOrderService.getById(orderId);
		if(po == null) {
			result.setCode(Status.ERROR.getCode());
        	result.setMsg(Status.ERROR.getMsg());
            return result;
		}
		User user = usersService.queryUser(po.getUserId());
		if(user == null) {
			result.setCode(Status.USER_NOT_EXIST.getCode());
        	result.setMsg(MessageFormat.format(Status.USER_NOT_EXIST.getMsg(), ""));
            return result;
		}
		if(user.getBalance() != null && user.getBalance().compareTo(po.getRealAmount()) < 0) {
			result.setCode(Status.INSUFFICIENT_ACCOUNT_BALANCE.getCode());
        	result.setMsg(Status.INSUFFICIENT_ACCOUNT_BALANCE.getMsg());
            return result;
		}
		//amountCombine 实付金额记录
		BigDecimal amountCombine = po.getAmount().subtract(po.getDiscountAmount());
		//关联算力券信息 状态、应付金额、实付金额、关联订单号
		if (Objects.nonNull(couponDetailId)) {
			//获取优惠券面额
			Coupondetail coupondetail = couponDetailService.getCouponDetailById(couponDetailId);
			BigDecimal useRuleAmount = new BigDecimal(coupondetail.getUseRuledeno().toString());
			//应付金额-优惠券面额=实付金额
			System.out.println(useRuleAmount);
			amountCombine = amountCombine.subtract(useRuleAmount);
			Couponbill updateCouponbill = new Couponbill();
			updateCouponbill.setCoupondetailId(couponDetailId);
			updateCouponbill.setUseAccount(String.valueOf(loginUser.getId()));
			updateCouponbill.setCouponState("已使用");
			updateCouponbill.setBillNo(po.getNo());
			updateCouponbill.setPayableValue(po.getRealAmount());
			updateCouponbill.setPaymentValue(amountCombine);
			couponbillService.updateCouponbillByDetailId(updateCouponbill, coupondetail);
		}
		//计算实际付款后余额
		BigDecimal balance = user.getBalance().subtract(amountCombine);
		// 记录消费明细
		String trans_no = generateNo();
		saveUserBalance(user.getId(), trans_no, amountCombine, user.getBalance(), po.getNo(), 0, balance);
		// 扣除用户余额
		user.setBalance(balance);
		usersService.updateById(user);
		// 修改订单状态和金额
		po.setPayTime(DateUtils.getCurrentDate());
		po.setPayStatus(1);
		po.setRealAmount(amountCombine);
		po.setDiscountAmount(po.getAmount().subtract(amountCombine));
		productOrderService.updateById(po);


		result.setCode(Status.SUCCESS.getCode());
    	result.setMsg(Status.SUCCESS.getMsg());
        return result;
	}

	public Result<Object> queryPayDetail(User loginUser, Integer pageNo, Integer pageSize, String searchVal) {
		Result<Object> result = new Result<>();
        if (loginUser.getRoleId() != null && loginUser.getRoleId().intValue() != 1) {
            result.setCode(Status.USER_NO_OPERATION_PERM.getCode());
        	result.setMsg(Status.USER_NO_OPERATION_PERM.getMsg());
            return result;
        }
        QueryWrapper<UserPayDetail> qw = new QueryWrapper<UserPayDetail>();
        if(StringUtils.isNotBlank(searchVal)) {
        	qw.eq("user_id", searchVal);
        }
        qw.orderByDesc("pay_time");
        Page<UserPayDetail> page = new Page<>(pageNo, pageSize);
		page = page(page, qw);
		if(page.getRecords() != null && page.getRecords().size() > 0) {
			for(UserPayDetail up : page.getRecords()) {
				User user = usersService.queryUser(up.getUserId());
				up.setUserName(user != null ? user.getUserName() : "");
			}
		}
		PageInfo<UserPayDetail> pageInfo = new PageInfo<>(pageNo, pageSize);
        pageInfo.setTotal((int) page.getTotal());
        pageInfo.setTotalList(page.getRecords());
        result.setData(pageInfo);

        result.setCode(Status.SUCCESS.getCode());
    	result.setMsg(Status.SUCCESS.getMsg());
        return result;
	}

	private void savePayDetail(Integer userId, BigDecimal payPrice, BigDecimal userBalance, String userName, BigDecimal balance) {
		String trans_no = generateNo();
		Date time = new Date();
		UserPayDetail detail = new UserPayDetail();
		detail.setPayNo(trans_no);
		detail.setPayTime(time);
		detail.setUserId(userId);
		detail.setPayPrice(payPrice);
		detail.setUserBalance(balance);
		detail.setPayType(1);
		detail.setPaySource(1);
		save(detail);

		saveUserBalance(userId, trans_no, payPrice, userBalance, "充值账户：" + userName, 2, balance);
	}

	private void saveUserBalance(Integer userId, String trnasNo, BigDecimal payPrice, BigDecimal userBalance, String info, Integer types, BigDecimal balance) {
		Date time = new Date();
		if (types == 2) {
			// 充值

			Bill bill = new Bill();
			bill.setBillNo(trnasNo);
			bill.setUserId(userId);
			// 交易类型 收入
			bill.setBillType(1);
			bill.setTradeType(types);
			// 交易渠道 平台充值
			bill.setTradeChannel(1);
			bill.setBillNumber(payPrice);
			bill.setOrderNo(info);
			bill.setCreateTime(time);
			bill.setBalance(balance);
			billService.saveBill(bill);
		} else if (types == 0) {
			// 用户消费
			Bill bill = new Bill();
			bill.setBillNo(trnasNo);
			bill.setUserId(userId);
			// 交易类型 支出
			bill.setBillType(0);
			bill.setTradeType(types);
			// 交易渠道 账户余额
			bill.setTradeChannel(0);
			bill.setBillNumber(payPrice);
			bill.setOrderNo(info);
			bill.setCreateTime(time);
			bill.setBalance(balance);
			billService.saveBill(bill);

			// 管理员记录一笔收入
			saveUserBalance(userId, trnasNo, payPrice, userBalance, info, 1, balance);
		} else if (types == 1) {
			User admin = usersService.queryUser(1);
			BigDecimal adminBalance = admin.getBalance().add(payPrice);
			// 平台消费 录入管理员收支明细
			Bill bill = new Bill();
			bill.setBillNo(trnasNo);
			bill.setUserId(1);
			// 交易类型 收入
			bill.setBillType(1);
			bill.setTradeType(types);
			// 交易渠道 账户余额
			bill.setTradeChannel(0);
			bill.setBillNumber(payPrice);
			bill.setOrderNo(info);
			bill.setCreateTime(time);
			bill.setBalance(adminBalance);
			billService.saveBill(bill);
		}
	}



	private String generateNo() {
		return DateUtil.getNowYYYYMMDDHHmmss() + RandomStringUtils.random(6, '1','2','3','4','5','6','7','8','9','0');
	}
}
